<!doctype html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <title>音频替换 | TEFS</title>
  <style>
    /* ========== 全局基础 ========== */
    *{margin:0;padding:0;box-sizing:border-box;font-family:"Microsoft YaHei",Arial,sans-serif}
    body{background-color:transparent;color:#333;position:relative;padding-top:60px;padding-bottom:40px;transition:background-color .3s,color .3s}

    /* 视频背景 */
    .background-container{position:fixed;top:0;left:0;width:100%;height:100%;z-index:-1;overflow:hidden;background:#000}
    .background-video{position:absolute;top:50%;left:50%;min-width:100%;min-height:100%;width:auto;height:auto;transform:translate(-50%,-50%);filter:brightness(.6);opacity:0;transition:opacity .5s}
    .background-video.loaded{opacity:1}

    /* 顶部导航（固定 60px） */
    .top-nav{position:fixed;top:0;left:0;right:0;height:60px;display:flex;align-items:center;justify-content:space-between;padding:0 20px;background:rgba(255,255,255,.9);box-shadow:0 1px 2px rgba(0,0,0,.08);z-index:1000;transition:background-color .3s ease;}
    .top-nav .logo{font-size:18px;font-weight:bold;color:#333;transition:color .3s ease;}
    .top-nav .user-area{display:flex;align-items:center;gap:12px}
    .top-nav .user-area span{color:#666;transition:color .3s ease;}

    /* 按钮统一样式 */
    .logout-btn,.profile-btn,.back-btn{
      padding:6px 14px;
      background-color:#ff6347;
      color:#fff;
      border:none;
      border-radius:4px;
      cursor:pointer;
      font-size:14px;
      transition:background-color .2s;
    }
    .back-btn {
      padding: 6px 14px;
      background-color: #50d8e0;
      color: #fff;
      border: none;
      border-radius: 4px;
      cursor: pointer;
      transition: background-color 0.2s;
      margin-right: 10px;
    }

    .back-btn:hover {
      background-color: #40bec7;
    }
    .profile-btn{background-color:#4a86e8;margin-right:10px}
    .profile-btn:hover{background-color:#3a76d8}
    .logout-btn:hover{background-color:#e55236}

    /* 主容器、卡片等样式 */
    .container{max-width:1200px;margin:30px auto;padding:0 20px}
    .page-title{font-size:1.8rem;margin-bottom:20px;color:#fff;text-shadow:0 0 6px rgba(0,0,0,.6);transition:color .3s ease;}
    .card{background:rgba(255,255,255,.75);border-radius:8px;padding:24px;margin-bottom:20px;box-shadow:0 2px 10px rgba(0,0,0,.08);transition:background-color .3s ease, border-color .3s ease;}
    .upload-area{
        display:flex;
        flex-direction: row;
        justify-content: center;
        align-items: center;
        gap: 30px;
        width: 100%;
      }
    .upload-box{
      border:2px dashed #999;
      border-radius:8px;
      padding:60px 20px;
      width:100%;
      max-width:400px;
      text-align:center;
      cursor:pointer;
      transition:border-color .3s, background-color .3s ease;
      min-height:220px;
    }
    .upload-box:hover{border-color:#50d8e0}
    .upload-icon{
      font-size:64px;
      margin-bottom:15px;
      transition:color .3s ease;
    }
    .file-name{font-weight:bold;color:#333;transition:color .3s ease;}
    .file-input{display:none}
    .time-controls{
      display:flex;
      gap:20px;
      margin-bottom:20px;
      justify-content: center;
    }
    .time-group{
      width: 300px;
    }
    .time-label{display:block;margin-bottom:6px;color:#555;transition:color .3s ease;}
    .time-input{
      width: 100%;
      padding:8px;
      border:1px solid #ccc;
      border-radius:4px;
      transition:background-color .3s ease, border-color .3s ease, color .3s ease;
    }
    .submit-btn{
      display:block;
      padding:12px;
      background:#50d8e0;
      color:#fff;
      border:none;
      border-radius:8px;
      font-size:16px;
      cursor:pointer;
      max-width: 800px;
      margin: 0 auto;
      transition:background-color .3s ease;
    }
    .submit-btn:hover{background:#40bec7}

    /* 表格样式（修复对齐问题） */
    .task-table{width:100%;border-collapse:collapse}
    .task-table th,.task-table td{
      padding:12px 8px;
      border-bottom:1px solid #eee;
      vertical-align: middle; /* 垂直居中对齐 */
      transition:border-color .3s ease, color .3s ease;
    }
    /* 按列设置对齐方式和宽度 */
    .task-table th:nth-child(1), .task-table td:nth-child(1) {
      text-align: left; /* 视频文件列 */
      width: 30%;
    }
    .task-table th:nth-child(2), .task-table td:nth-child(2) {
      text-align: left; /* 音频文件列 */
      width: 20%;
    }
    .task-table th:nth-child(3), .task-table td:nth-child(3) {
      text-align: center; /* 时间范围列 */
      width: 15%;
    }
    .task-table th:nth-child(4), .task-table td:nth-child(4) {
      text-align: center; /* 状态列 */
      width: 10%;
    }
    .task-table th:nth-child(5), .task-table td:nth-child(5) {
      text-align: center; /* 创建时间列 */
      width: 15%;
    }
    .task-table th:nth-child(6), .task-table td:nth-child(6) {
      text-align: center; /* 操作列 */
      width: 10%;
    }
    .task-table th{background:rgba(248,249,250,.75);color:#666;font-weight:500;transition:background-color .3s ease, color .3s ease;}
    .status-processing{color:#f0ad4e}
    .status-completed{color:#5cb85c}
    .status-failed{color:#d9534f}
    .download-btn{padding:4px 8px;background:#5cb85c;color:#fff;border:none;border-radius:3px;cursor:pointer;font-size:13px;transition:background-color .3s ease;}

    /* 底部 */
    .footer{position:fixed;bottom:0;left:0;width:100%;height:40px;background:rgba(51,51,51,.9);color:#fff;display:flex;align-items:center;justify-content:center;font-size:12px;line-height:1;transition:background-color .3s ease, color .3s ease;}

    /* 深色模式 */
    body.dark-mode .file-name {
      color: #fff;
    }
    body.dark-mode .time-label {
      color: #fff;
    }
    body.dark-mode .time-input {
      color: #fff;
      background-color: #333;
      border-color: #555;
    }
    body.dark-mode{background:#121212;color:#e0e0e0}
    body.dark-mode .top-nav{background:rgba(30,30,30,.9)}
    body.dark-mode .top-nav .logo,body.dark-mode .top-nav .user-area span{color:#fff}
    body.dark-mode .card{background:rgba(30,30,30,.7)}
    body.dark-mode .task-table th,body.dark-mode .task-table td{
      border-color:#505050;
      color:#e0e0e0;
      vertical-align: middle; /* 同步垂直居中 */
    }
    body.dark-mode .task-table th{background:rgba(40,40,40,.5)}
  </style>
</head>

<body>
  <!-- 视频背景 -->
  <div class="background-container">
    <video class="background-video" autoplay muted loop playsinline>
      <source src="/static/videos/c1.mp4" type="video/mp4">
      您的浏览器不支持视频背景
    </video>
  </div>

  <!-- 顶部导航 -->
  <div class="top-nav">
    <div class="logo">TEFS</div>
    <div class="user-area">
        <a href="{{ url_for('features') }}">
            <button class="back-btn">返回功能页</button>
        </a>
        <span>用户</span>
        <span>{{ username }}</span>
        <a href="{{ url_for('profile') }}">
            <button class="profile-btn">账户设置</button>
        </a>
        <a href="{{ url_for('logout') }}">
            <button class="logout-btn">登出</button>
        </a>

      <!-- 深色模式切换 -->
      <button id="theme-toggle" style="margin-left:10px;padding:6px 12px;background:#4a86e8;color:#fff;border:none;border-radius:4px;cursor:pointer;transition:background-color .3s ease;">切换深色模式</button>
    </div>
  </div>

  <!-- 主容器 -->
  <div class="container">
    <h1 class="page-title">音频替换</h1>

    <!-- 上传区域 -->
    <div class="card">
      <div class="upload-area">
        <div class="upload-box">
          <input type="file" id="videoInput" class="file-input" accept="video/*">
          <label for="videoInput" style="cursor:pointer">
            <div class="upload-icon">🎬</div>
            <div>选择视频文件</div>
            <div class="file-name" id="videoName">未选择</div>
          </label>
        </div>

        <div class="upload-box">
          <input type="file" id="audioInput" class="file-input" accept="audio/*">
          <label for="audioInput" style="cursor:pointer">
            <div class="upload-icon">🎵</div>
            <div>选择音频文件</div>
            <div class="file-name" id="audioName">未选择</div>
          </label>
        </div>
      </div>
    </div>

    <!-- 时间设置 -->
    <div class="card">
      <h3 style="margin-bottom:15px; text-align: center;transition:color .3s ease;">设置替换时间</h3>
      <div class="time-controls">
        <div class="time-group">
          <label class="time-label">开始时间 (秒)</label>
          <input type="number" id="startTime" class="time-input" value="0" min="0" step="0.1">
        </div>
        <div class="time-group">
          <label class="time-label">结束时间 (秒)</label>
          <input type="number" id="endTime" class="time-input" min="0" step="0.1" placeholder="留空到结尾">
        </div>
      </div>
      <button id="submitBtn" class="submit-btn">开始替换音频</button>
    </div>

    <!-- 任务列表 -->
    <div class="card">
      <div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:15px">
        <h3 style="transition:color .3s ease;">音频替换任务</h3>
        <button class="refresh-btn" style="background:none;border:none;color:#4a86e8;cursor:pointer;transition:color .3s ease;">刷新</button>
      </div>
      <table class="task-table">
        <thead>
          <tr>
            <th>视频文件</th><th>音频文件</th><th>时间范围</th>
            <th>状态</th><th>创建时间</th><th>操作</th>
          </tr>
        </thead>
        <tbody id="tasksTable">
          {% if tasks %}
            {% for task in tasks %}
            <tr>
              <td>{{ task.video_name|truncate(20) }}</td>
              <td>{{ task.audio_name|truncate(20) }}</td>
              <td>{{ task.start_time|round(1) }}s -
                {% if task.end_time %}{{ task.end_time|round(1) }}s{% else %}结束{% endif %}
              </td>
              <td class="status-{{ task.status }}">
                {% if task.status=='processing' %}处理中{% elif task.status=='completed' %}已完成{% else %}失败{% endif %}
              </td>
              <td>{{ task.created_at.strftime('%Y-%m-%d %H:%M') }}</td>
              <td>
                {% if task.status=='completed' %}
                  <a href="{{ url_for('download_audio_replace',task_id=task.id) }}"><button class="download-btn">下载</button></a>
                {% elif task.status=='failed' and task.output_name %}
                  <a href="{{ url_for('download',filename=task.output_name) }}"><button class="download-btn">错误报告</button></a>
                {% endif %}
              </td>
            </tr>
            {% endfor %}
          {% else %}
            <tr><td colspan="6" style="text-align:center;padding:20px;color:#888;transition:color .3s ease;">暂无音频替换任务</td></tr>
          {% endif %}
        </tbody>
      </table>
    </div>
  </div>

  <!-- 底部 -->
  <div class="footer">产品由句号团队开发</div>

  <!-- 脚本 -->
  <script>
    document.addEventListener('DOMContentLoaded', function() {
        /* 视频背景淡入 */
        const bgVideo = document.querySelector('.background-video');
        bgVideo.addEventListener('loadeddata', () => bgVideo.classList.add('loaded'));
        setTimeout(() => !bgVideo.classList.contains('loaded') && bgVideo.classList.add('loaded'), 3000);

        /* 深色模式持久化 */
        (function() {
            const dark = 'dark-mode';
            const body = document.body;
            const toggleBtn = document.getElementById('theme-toggle');
            const saved = localStorage.getItem(dark) === 'true';
            if (saved) { body.classList.add(dark); toggleBtn.textContent = '切换浅色模式'; }
            toggleBtn.addEventListener('click', () => {
                body.classList.toggle(dark);
                const on = body.classList.contains(dark);
                localStorage.setItem(dark, on);
                toggleBtn.textContent = on ? '切换浅色模式' : '切换深色模式';
            });
        })();

        /* 文件提示 */
        document.getElementById('videoInput').addEventListener('change', e => {
            document.getElementById('videoName').textContent = e.target.files[0]?.name || '未选择';
        });
        document.getElementById('audioInput').addEventListener('change', e => {
            document.getElementById('audioName').textContent = e.target.files[0]?.name || '未选择';
        });

        /* 提交任务 */
        document.getElementById('submitBtn').addEventListener('click', async () => {
            const video = document.getElementById('videoInput').files[0];
            const audio = document.getElementById('audioInput').files[0];
            const start = document.getElementById('startTime').value;
            const end = document.getElementById('endTime').value || '';

            if (!video || !audio) {
                alert('请选择视频和音频文件');
                return;
            }

            const fd = new FormData();
            fd.append('video', video);
            fd.append('audio', audio);
            fd.append('start_time', start);
            if (end) fd.append('end_time', end);

            const btn = document.getElementById('submitBtn');
            const originalBtnText = btn.textContent;
            btn.textContent = '处理中...';
            btn.disabled = true;

            try {
                const response = await fetch("{{ url_for('audio_replace') }}", { method: 'POST', body: fd });
                const result = await response.json();

                if (result.success) {
                    createAndInsertAudioProgressTask(result.task_id, video.name, audio.name, start, end);
                    startAudioProgressPolling(result.task_id);
                } else {
                    alert('提交失败：' + (result.message || '未知错误'));
                }
            } catch (error) {
                alert('请求失败: ' + error);
            } finally {
                btn.textContent = originalBtnText;
                btn.disabled = false;
            }
        });

        /* 刷新按钮 */
        document.querySelector('.refresh-btn').addEventListener('click', () => {
            location.reload();
        });
    });

    /* 创建进度条行 */
    function createAndInsertAudioProgressTask(taskId, videoName, audioName, startTime, endTime) {
        const tableBody = document.getElementById('tasksTable');
        const timeRange = `${parseFloat(startTime).toFixed(1)}s - ${endTime ? parseFloat(endTime).toFixed(1) + 's' : '结束'}`;

        const newRowHTML = `
            <tr id="task-item-progress-${taskId}">
              <td>${videoName.length > 20 ? videoName.substring(0, 20) + '...' : videoName}</td>
              <td>${audioName.length > 20 ? audioName.substring(0, 20) + '...' : audioName}</td>
              <td>${timeRange}</td>
              <td class="status-processing" colspan="2">
                <div style="background-color:#e9ecef; border-radius:4px; height:20px; overflow:hidden;transition:background-color .3s ease;">
                  <div id="progress-bar-${taskId}" style="width:0%; height:100%; background-color:#f0ad4e; transition:width 0.4s ease;"></div>
                </div>
              </td>
              <td id="progress-text-${taskId}" style="font-weight:bold; text-align:center;transition:color .3s ease;">0%</td>
            </tr>
        `;
        tableBody.insertAdjacentHTML('afterbegin', newRowHTML);
    }

    /* 轮询更新进度 */
    function startAudioProgressPolling(taskId) {
        const progressBar  = document.getElementById(`progress-bar-${taskId}`);
        const progressText = document.getElementById(`progress-text-${taskId}`);
        let last = 0;
        let freezeTimer = null;

        const tick = async () => {
            try {
                const res = await fetch(`/audio_replace_progress/${taskId}`);
                const { progress = 0 } = res.ok ? await res.json() : {};

                const p = Math.max(progress, last);
                progressBar.style.width = `${p.toFixed(2)}%`;
                progressText.textContent = `${p.toFixed(2)}%`;

                if (p !== last) {
                    last = p;
                    clearTimeout(freezeTimer);
                    if (p < 100) freezeTimer = setTimeout(forceDone, 5000);
                }

                if (p >= 100) return location.reload();

                setTimeout(tick, 2000);
            } catch (e) {
                forceDone();
            }
        };

        function forceDone() {
            progressBar.style.width = '100%';
            progressText.textContent = '100.00%';
            setTimeout(() => location.reload(), 300);
        }

        tick();
    }
  </script>
</body>
</html>